package com.awesome.drag1.core

import android.app.Activity
import android.content.Context
import android.graphics.*
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import androidx.appcompat.app.AppCompatActivity
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageView
import com.awesome.drag1.R
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.load.resource.gif.GifDrawable
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.awesome.drag1.extension.Utils
import com.awesome.drag1.extension.glide.GlideHelper
import com.awesome.drag1.extension.entities.DraggableImageInfo
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.view_draggable_simple_image.view.*

/**
 * 单张图片查看器
 *
 * 1. 支持动画进入和退出
 * 2. 支持拖放退出
 *
 * */
class DraggableImageView : FrameLayout {

    interface ActionListener {
        fun onExit() // drag to exit
    }

    private val TAG = javaClass.simpleName
    // 拖拽信息
    private var draggableImageInfo: DraggableImageInfo? = null
    var actionListener: ActionListener? = null
    // 当前加载的url
    private var currentLoadUrl = ""
    private var downloadDisposable: Disposable? = null
    private var draggableZoomCore: DraggableZoomCore? = null
    private var needFitCenter = true
    private var viewSelfWhRadio = 1f

    private var draggableZoomActionListener = object : DraggableZoomCore.ActionListener {
        override fun currentAlphaValue(alpha: Int) {
            background = ColorDrawable(Color.argb(alpha, 0, 0, 0))
        }

        override fun onExit() {
            actionListener?.onExit()
        }
    }

    private val exitAnimatorCallback = object : DraggableZoomCore.ExitAnimatorCallback {
        override fun onStartInitAnimatorParams() {
            mDraggableImageViewPhotoView.scaleType = ImageView.ScaleType.CENTER_CROP
        }
    }

    constructor(context: Context) : super(context) {
        initView()
    }

    constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) {
        initView()
    }

    private fun initView() {
        LayoutInflater.from(context).inflate(R.layout.view_draggable_simple_image, this)
        layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)

        setOnClickListener {
            clickToExit()
        }

        mDraggableImageViewPhotoView.setOnClickListener {
            clickToExit()
        }

        // 加载原图
        mDraggableImageViewViewOriginImage.setOnClickListener {
            loadImage(draggableImageInfo?.originImg ?: "", false)
        }

        mDraggableImageViewViewOProgressBar.indeterminateDrawable.setColorFilter(
            Color.parseColor("#ebebeb"),
            PorterDuff.Mode.MULTIPLY
        )
    }

    /**
     * 点击的关闭动画
     */
    private fun clickToExit() {
        if (draggableZoomCore?.isAnimating == true) return
        mDraggableImageViewViewOProgressBar.visibility = View.GONE
        if (mDraggableImageViewPhotoView.scale != 1f) {
            mDraggableImageViewPhotoView.setScale(1f, true)
        } else {
            draggableZoomCore?.adjustScaleViewToCorrectLocation()
            draggableZoomCore?.exitWithAnimator(false)
            downloadDisposable?.dispose()
        }
    }

    /**
     * 拖拽支持
     * */
    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        val isIntercept = super.onInterceptTouchEvent(ev)
        if (draggableZoomCore?.isAnimating == true) {
            return false
        }
        if (mDraggableImageViewPhotoView.scale != 1f) {
            return false
        }
        if (!mDraggableImageViewPhotoView.attacher.displyRectIsFromTop()) {
            return false
        }
        if (mDraggableImageViewViewOProgressBar.visibility == View.VISIBLE) {    // loading 时不允许拖拽退出
            return false
        }
        return draggableZoomCore?.onInterceptTouchEvent(isIntercept, ev) ?: false
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        draggableZoomCore?.onTouchEvent(event)
        return super.onTouchEvent(event)
    }

    /**
     * 展开时动画
     */
    fun showImageWithAnimator(paramsInfo: DraggableImageInfo) {
        draggableImageInfo = paramsInfo
        currentLoadUrl = ""
        refreshOriginImageInfo()
        GlideHelper.retrieveImageWhRadioFromMemoryCache(
            context,
            paramsInfo.thumbnailImg
        ) { inMemCache, whRadio, isGif ->
            // 设置拖拽图片的宽高比
            draggableImageInfo?.draggableInfo?.scaledViewWhRadio = whRadio
            post {
                // 容器的宽高比
                viewSelfWhRadio = (width * 1f / height)
                // 原图的宽高比太大，需要剪裁。图片的宽高比 > 容器的宽高比
                needFitCenter = whRadio > viewSelfWhRadio

                // 宽高比失效，或者是Gif并且不需要剪裁
                if (!paramsInfo.draggableInfo.isValid() || (isGif && !needFitCenter) ) {
                    //退出的时候不要再开启动画
                    paramsInfo.draggableInfo = DraggableParamsInfo()
                    showImage(paramsInfo)
                    return@post
                }

                draggableZoomCore = DraggableZoomCore(
                    paramsInfo.draggableInfo,
                    mDraggableImageViewPhotoView,
                    width,
                    height,
                    draggableZoomActionListener,
                    exitAnimatorCallback
                )
                draggableZoomCore?.adjustScaleViewToInitLocation()
                loadAvailableImage(true, inMemCache)
            }
        }
    }

    fun showImage(paramsInfo: DraggableImageInfo) {
        draggableImageInfo = paramsInfo
        currentLoadUrl = ""
        refreshOriginImageInfo()
        GlideHelper.retrieveImageWhRadioFromMemoryCache(
            context,
            paramsInfo.thumbnailImg
        ) { inMemCache, whRadio , isGif->
            draggableImageInfo?.draggableInfo?.scaledViewWhRadio = whRadio
            post {
                viewSelfWhRadio = (width * 1f / height)
                needFitCenter = whRadio > viewSelfWhRadio

                draggableZoomCore = DraggableZoomCore(
                    paramsInfo.draggableInfo,
                    mDraggableImageViewPhotoView,
                    width,
                    height,
                    draggableZoomActionListener,
                    exitAnimatorCallback
                )
                draggableZoomCore?.adjustScaleViewToCorrectLocation()
                loadAvailableImage(false, inMemCache)
            }
        }
    }

    /**
     * startAnimator,开始动画
     * imgInMemCache,Glide加载成功为true
     */
    private fun loadAvailableImage(startAnimator: Boolean, imgInMemCache: Boolean) {
        if ((context as? AppCompatActivity)?.isDestroyed == true || (context as? AppCompatActivity)?.isFinishing == true) {
            return
        }

        mDraggableImageViewPhotoView.scaleType = ImageView.ScaleType.FIT_CENTER
        mDraggableImageViewPhotoView.setImageResource(R.drawable.place_holder_transparent)

        val thumnailImg = draggableImageInfo!!.thumbnailImg
        val originImg = draggableImageInfo!!.originImg

        // 是否有连接的wifi
        val wifiIsConnect = Utils.isWifiConnected(context)

        // 原图是否已经有缓存
        val originImgInCache = GlideHelper.imageIsInCache(context, originImg)

        // 选择url
        val targetUrl = if (wifiIsConnect || originImgInCache) originImg else thumnailImg

        // 不是加载原图，显示加载原图的按钮
        setViewOriginImageBtnVisible(targetUrl != originImg)

        // 加载网络图片
        if (imgInMemCache) {
            // 加载缩略图
            loadImage(thumnailImg, originImgInCache)
        }

        // 展开时动画
        if (imgInMemCache && startAnimator) {  //只有缩略图在缓存中时，才播放缩放入场动画
            // 进入动画
            draggableZoomCore?.enterWithAnimator(object :
                DraggableZoomCore.EnterAnimatorCallback {
                override fun onEnterAnimatorStart() {
                    mDraggableImageViewPhotoView.scaleType = ImageView.ScaleType.CENTER_CROP
                }

                override fun onEnterAnimatorEnd() {
                    if (needFitCenter) {
                        mDraggableImageViewPhotoView.scaleType = ImageView.ScaleType.FIT_CENTER
                        draggableZoomCore?.adjustViewToMatchParent()
                    }
                    // 加载目标url
                    loadImage(targetUrl, originImgInCache)
                }
            })
        } else {
            loadImage(targetUrl, originImgInCache)
            if (needFitCenter) {
                draggableZoomCore?.adjustViewToMatchParent()
            }
        }
    }

    /**
     * url：网络图url
     * originIsInCache：原图是否已经有缓存
     */
    private fun loadImage(url: String, originIsInCache: Boolean) {

        // 多次加载返回
        if (url == currentLoadUrl) return

        if ((context is Activity) && ((context as Activity).isFinishing || (context as Activity).isDestroyed)) {
            return
        }

        currentLoadUrl = url

        if (url == draggableImageInfo?.originImg && !originIsInCache) {
            mDraggableImageViewViewOProgressBar.visibility = View.VISIBLE
        }

        val options = RequestOptions().priority(Priority.HIGH) //被查看的图片应该由最高的请求优先级

        Glide.with(context)
            .load(url)
            .apply(options)
            .into(object : SimpleTarget<Drawable>() {
                override fun onResourceReady(
                    resource: Drawable,
                    transition: Transition<in Drawable>?
                ) {
                    val isGif = resource is GifDrawable
                    mDraggableImageViewViewOProgressBar.visibility = View.GONE
                    // 网络图片宽高比
                    val whRadio = resource.intrinsicWidth * 1f / resource.intrinsicHeight
                    // 长图，网络图片宽高比<容器宽高比
                    val longImage = whRadio < viewSelfWhRadio

                    if (isGif) {
                        if (longImage){
                            mDraggableImageViewPhotoView.scaleType = ImageView.ScaleType.CENTER_INSIDE
                        }
                        Glide.with(context).load(url).into(mDraggableImageViewPhotoView)
                    } else {
                        //普通图片已经做了缩放 -> 宽度缩放至屏幕的宽度
                        mDraggableImageViewPhotoView.scaleType = if (longImage)ImageView.ScaleType.CENTER_CROP else ImageView.ScaleType.FIT_CENTER
                        // 设置网络图片
                        mDraggableImageViewPhotoView.setImageBitmap(translateToFixedBitmap(resource))
                    }

                    if (url == draggableImageInfo?.originImg) {
                        mDraggableImageViewViewOriginImage.visibility = View.GONE
                    }
                }

                override fun onLoadFailed(errorDrawable: Drawable?) {
                    super.onLoadFailed(errorDrawable)
                    mDraggableImageViewViewOProgressBar.visibility = View.GONE
                }
            })
    }

    //avoid oom
    private fun translateToFixedBitmap(originDrawable: Drawable): Bitmap? {
        // 网络图片宽高比
        val whRadio = originDrawable.intrinsicWidth * 1f / originDrawable.intrinsicHeight
        // 屏幕宽度
        val screenWidth = Utils.getScreenWidth()

        var bpWidth = if (this@DraggableImageView.width != 0) {
            // 网络图片宽高 > 容器宽度
            if (originDrawable.intrinsicWidth > this@DraggableImageView.width) {
                this@DraggableImageView.width
            } else {
                originDrawable.intrinsicWidth
            }
        } else {
            // 容器宽度=0，默认容器宽度为屏幕宽度
            if (originDrawable.intrinsicWidth > screenWidth) {
                screenWidth
            } else {
                originDrawable.intrinsicWidth
            }
        }

        // 最大宽度为屏幕宽度
        if (bpWidth > screenWidth) bpWidth = screenWidth

        // 高度为网络图片宽高比折算
        val bpHeight = (bpWidth * 1f / whRadio).toInt()

        Log.d(TAG, "bpWidth : $bpWidth  bpHeight : $bpHeight")

        var bp = Glide.get(context).bitmapPool.get(
            bpWidth,
            bpHeight,
            if (bpHeight > 4000) Bitmap.Config.RGB_565 else Bitmap.Config.ARGB_8888
        )

        if (bp == null) {
            bp = Bitmap.createBitmap(
                bpWidth,
                bpHeight,
                Bitmap.Config.ARGB_8888
            )
        }

        val canvas = Canvas(bp)
        originDrawable.setBounds(0, 0, bpWidth, bpHeight)
        originDrawable.draw(canvas)

        return bp
    }

    private fun refreshOriginImageInfo() {
        if (draggableImageInfo!!.imageSize > 0) {
            mDraggableImageViewViewOriginImage.text =
                "查看原图(${Utils.formatImageSize(draggableImageInfo?.imageSize ?: 0)})"
        } else {
            mDraggableImageViewViewOriginImage.text = "查看原图"
        }
    }

    private fun setViewOriginImageBtnVisible(visible: Boolean) {
        mDraggableImageViewViewOriginImage.visibility = if (visible) View.VISIBLE else View.GONE
    }

    fun closeWithAnimator() {
        draggableZoomCore?.adjustScaleViewToCorrectLocation()
        draggableZoomCore?.exitWithAnimator(false)
        downloadDisposable?.dispose()
    }

}